﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;

namespace Andrewl.XnaHelpers.Guide_Helper
{
    public static class GuideHelper
    {
        //Hold a queue (first in first out data structure) so that it shows the guides in the order they were called
        public static Queue<GuideControl> objects = new Queue<GuideControl>();
        //Update our timer and see if we should show a new guide
        private static bool exceptionThrown = false;

        public static void Update()
        {
            if (objects.Count > 0)
            {
                if (!Guide.IsVisible)
                {
                    try
                    {
                       objects.Peek().Display();
                    }
                    catch (Exception e)
                    {
                       exceptionThrown = true;
                    }
                    finally { }        
                    if (!exceptionThrown)
                    {
                        objects.Dequeue();
                    }
                    exceptionThrown = false;
                }
            }
        }
        //manually adds a guidecontrol to our queue
        public static void Add(GuideControl item)
        {
            objects.Enqueue(item);
        }
        /// <summary>
        /// Adds a messagebox to the que of guide items to be displayed
        /// </summary>
        /// <param name="Title">The text that will appear at the top of the messagebox</param>
        /// <param name="Text">The text that will occupy the center of the message box, this is where your message goes</param>
        /// <param name="Buttons">Pass an array of strings that will be the button names</param>
        /// <param name="Focus">This determines which button is selected when the box opens its is zero based</param>
        /// <param name="Icon">The icon to appear in the upper left corner of the box</param>
        /// <param name="CompleteFunction">A function you wrote that will receive the int value of which button was pressed so you can take an according action</param>
        public static void ShowMessageBox(string Title, string Text, string[] Buttons, int Focus, MessageBoxIcon Icon, Action<int> CompleteFunction)
        {
            Add(new ShowMessageBox(Title, Text, Buttons, Focus, Icon, CompleteFunction));
        }
        /// <summary>
        /// Adds a keyboardInput to the que of guide items to be displayed
        /// </summary>
        /// <param name="Index">Controlling PlayerIndex</param>
        /// <param name="Title">The title to appear on the keyboard</param>
        /// <param name="Description">The description to tell the user what to enter</param>
        /// <param name="DefaultText">The text that will appear in the textbox when it is first opended</param>
        /// <param name="CompleteFunction">A function that you wrote that will receive the string value of what the user entered</param>
        public static void ShowKeyboard(PlayerIndex Index, string Title, string Description, string DefaultText, Action<string> CompleteFunction)
        {
            Add(new ShowKeyboard(Index, Title, Description, DefaultText, CompleteFunction));
        }
        /// <summary>
        /// Opens the storage device selector
        /// </summary>
        /// <param name="CompleteFunction">A function that you wrote that will recieve the StorageDevice that was selected</param>
        public static void ShowStorageDeviceSelector(Action<StorageDevice> CompleteFunction)
        {
            Add(new ShowStorageDeviceSelector(CompleteFunction));
        }
        /// <summary>
        /// Opens the friends lists for the specified controller
        /// </summary>
        /// <param name="Index"></param>
        public static void ShowFriends(PlayerIndex Index)
        {
            Add(new ShowFriends(Index));
        }

        public static void ShowFriendRequest(PlayerIndex Index, Gamer Gamer)
        {
            Add(new ShowFriendRequest(Index, Gamer));
        }

        public static void ShowComposeMessage(PlayerIndex Index, string Message, Gamer[] Gamer)
        {
            Add(new ShowComposeMessage(Index, Message, Gamer));
        }

        public static void ShowGameInvite(PlayerIndex Index, Gamer[] Gamer)
        {
            Add(new ShowGameInvite(Index, Gamer));
        }

        public static void ShowGamerCard(PlayerIndex Index, Gamer Gamer)
        {
            Add(new ShowGamerCard(Index, Gamer));
        }

        public static void ShowMarketplace(PlayerIndex Index)
        {
            Add(new ShowMarketplace(Index));
        }

        public static void ShowMessages(PlayerIndex Index)
        {
            Add(new ShowMessages(Index));
        }

        public static void ShowParty(PlayerIndex Index)
        {
            Add(new ShowParty(Index));
        }

        public static void ShowPartySessions(PlayerIndex Index)
        {
            Add(new ShowPartySessions(Index));
        }

        public static void ShowPlayerReview(PlayerIndex Index, Gamer Gamer)
        {
            Add(new ShowPlayerReivew(Index, Gamer));
        }

        public static void ShowPlayers(PlayerIndex Index)
        {
            Add(new ShowPlayers(Index));
        }

        public static void ShowSignIn(int NumberOfPanes, bool OnlineProfilesOnly)
        {
            Add(new ShowSignIn(NumberOfPanes, OnlineProfilesOnly));
        }

    }

    public abstract class GuideControl
    {
        public GuideControl()
        { }
        public abstract void Display();
    }

    public class ShowMessageBox : GuideControl
    {
        public string Title;

        public string Text;

        public string[] Buttons;

        public int FocusButton;

        public MessageBoxIcon Icon;

        public Action<int> Complete;

        public int? resultInt;

        public ShowMessageBox(string TitleArg, string TextArg, string[] ButtonsArg, int FocusButtonArg, MessageBoxIcon IconArg, Action<int> CompleteFunction)
            : base()
        {
            Title = TitleArg;
            Text = TextArg;
            Buttons = ButtonsArg;
            FocusButton = FocusButtonArg;
            Icon = IconArg;
            Complete = CompleteFunction;
            resultInt = 9;
        }

        public override void Display()
        {
            Guide.BeginShowMessageBox(Title, Text, Buttons, FocusButton, Icon, Callback, (object)"MessageBox");
        }

        public void Callback(IAsyncResult result)
        {
            resultInt = Guide.EndShowMessageBox(result);
            if (resultInt != null)
            {
                if ((int)resultInt == 0 || (int)resultInt == 1 || (int)resultInt == 2)
                {
                    if (Complete != null)
                    {
                        Complete.Invoke((int)resultInt);
                    }
                    else
                    {
                        return;
                    }
                }
            }
            else
            {
                Complete.Invoke(-1);
            }
        }
    }

    public class ShowKeyboard : GuideControl
    {
        public PlayerIndex Controller;

        public string Title;

        public string Description;

        public string DefaultText;

        public Action<String> Complete;

        public string resultString;

        public ShowKeyboard(PlayerIndex IndexArg, string TitleArg, string DescriptionArg, string DefaultTextArg, Action<String> InputCompleteArg)
            : base()
        {
            Controller = IndexArg;
            Title = TitleArg;
            Description = DescriptionArg;
            DefaultText = DefaultTextArg;
            Complete = InputCompleteArg;
            resultString = null;
        }

        public override void Display()
        {
            Guide.BeginShowKeyboardInput(Controller, Title, Description, DefaultText, Callback, (object)"KeyboardInput");
        }

        public void Callback(IAsyncResult result)
        {
            resultString = Guide.EndShowKeyboardInput(result);
            if (resultString != null)
            {
                if (Complete == null)
                {
                    return;
                }
                else
                {
                    Complete.Invoke(resultString);
                }
            }
            else
                return;
        }
    }

    public class ShowStorageDeviceSelector : GuideControl
    {
        public StorageDevice returnDevice;

        public Action<StorageDevice> Complete;

        public ShowStorageDeviceSelector(Action<StorageDevice> InputComplete)
            : base()
        {
            Complete = InputComplete;
        }

        public override void Display()
        {
            Guide.BeginShowStorageDeviceSelector(Callback, (object)"DeviceSelecter");
        }

        public void Callback(IAsyncResult result)
        {
            returnDevice = Guide.EndShowStorageDeviceSelector(result);
            if (returnDevice != null)
            {
                if (Complete == null)
                {
                    throw new ArgumentNullException("The Callback function for a Storage Device Selector cannot be null, what's the point of a storage device selector if you can't retreive the device that is selected?");
                }
                else
                {
                    Complete(returnDevice);
                }
                return;
            }
            else
            {
                return;
            }
        }
    }

    public class ShowFriends : GuideControl
    {
        public PlayerIndex Controller;

        public ShowFriends(PlayerIndex index)
            : base()
        {
            Controller = index;
        }

        public override void Display()
        {
            Guide.ShowFriends(Controller);
        }
    }

    public class ShowFriendRequest : GuideControl
    {
        public PlayerIndex Controller;

        public Gamer Gamer;

        public ShowFriendRequest(PlayerIndex index, Gamer gamer)
        {
            Controller = index;
        }

        public override void Display()
        {
            Guide.ShowFriendRequest(Controller, Gamer);
        }
    }

    public class ShowComposeMessage : GuideControl
    {
        public PlayerIndex Controller;

        public string Text;

        public Gamer[] Recipients;

        public ShowComposeMessage(PlayerIndex index, string message)
            : base()
        {
            Controller = index;
            Text = message;
            Recipients = null;
        }

        public ShowComposeMessage(PlayerIndex index, string message, Gamer[] peopleToSendTo)
            : base()
        {
            Controller = index;
            Text = message;
            Recipients = peopleToSendTo;
        }

        public override void Display()
        {
            Guide.ShowComposeMessage(Controller, Text, Recipients);
        }
    }

    public class ShowGameInvite : GuideControl
    {
        public PlayerIndex Controller;

        public Gamer[] Recipients;

        public ShowGameInvite(PlayerIndex index)
            : base()
        {
            Controller = index;
            Recipients = null;
        }

        public ShowGameInvite(PlayerIndex index, Gamer[] gamersToSendTo)
        {
            Controller = index;
            Recipients = gamersToSendTo;
        }

        public override void Display()
        {
            Guide.ShowGameInvite(Controller, Recipients);
        }
    }

    public class ShowGamerCard : GuideControl
    {
        public PlayerIndex Controller;

        public Gamer Gamer;

        public ShowGamerCard(PlayerIndex index, Gamer gamerArg)
            : base()
        {
            Controller = index;
            Gamer = gamerArg;
        }

        public override void Display()
        {
            Guide.ShowGamerCard(Controller, Gamer);
        }
    }

    public class ShowMarketplace : GuideControl
    {
        public PlayerIndex Controller;

        public ShowMarketplace(PlayerIndex index)
            : base()
        {
            Controller = index;
        }

        public override void Display()
        {
            Guide.ShowMarketplace(Controller);
        }
    }

    public class ShowMessages : GuideControl
    {
        public PlayerIndex Controller;

        public ShowMessages(PlayerIndex index)
        {
            Controller = index;
        }

        public override void Display()
        {
            Guide.ShowMessages(Controller);
        }
    }

    public class ShowParty : GuideControl
    {
        public PlayerIndex Controller;

        public ShowParty(PlayerIndex index)
            : base()
        {
            Controller = index;
        }

        public override void Display()
        {
            Guide.ShowParty(Controller);
        }
    }

    public class ShowPartySessions : GuideControl
    {
        public PlayerIndex Controller;

        public ShowPartySessions(PlayerIndex index)
            : base()
        {
            Controller = index;
        }

        public override void Display()
        {
            Guide.ShowPartySessions(Controller);
        }
    }

    public class ShowPlayerReivew : GuideControl
    {
        public PlayerIndex Controller;

        public Gamer Gamer;

        public ShowPlayerReivew(PlayerIndex index, Gamer gamerArg)
            : base()
        {
            Controller = index;
            Gamer = gamerArg;
        }

        public override void Display()
        {
            Guide.ShowPlayerReview(Controller, Gamer);
        }
    }

    public class ShowPlayers : GuideControl
    {
        public PlayerIndex Controller;

        public ShowPlayers(PlayerIndex index)
            : base()
        {
            Controller = index;
        }

        public override void Display()
        {
            Guide.ShowPlayers(Controller);
        }
    }

    public class ShowSignIn : GuideControl
    {
        public int PaneCount;

        public bool OnlineOnly;

        public ShowSignIn(int numberOfPanes, bool xboxLiveOnly)
            : base()
        {
            PaneCount = numberOfPanes;
            OnlineOnly = xboxLiveOnly;
        }

        public override void Display()
        {
            Guide.ShowSignIn(PaneCount, OnlineOnly);
        }
    }
}
